package com.atguigu.school.service.impl;

import com.atguigu.school.constants.SchoolConstants;
import com.atguigu.school.mapper.AdminMapper;
import com.atguigu.school.mapper.StudentMapper;
import com.atguigu.school.mapper.TeacherMapper;
import com.atguigu.school.pojo.Admin;
import com.atguigu.school.commons.LoginForm;
import com.atguigu.school.pojo.Student;
import com.atguigu.school.pojo.Teacher;
import com.atguigu.school.service.SystemService;
import com.atguigu.school.commons.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;

@Service
public class SystemServiceImpl implements SystemService {

    /**
     * 访问管理员数据
     */
    @Autowired
    private AdminMapper adminMapper;

    /**
     * 访问学生数据
     */
    @Autowired
    private StudentMapper studentMapper;

    /**
     * 访问教师数据
     */
    @Autowired
    private TeacherMapper teacherMapper;

    /**
     * 日志记录器
     */
    private static final Logger logger = LoggerFactory.getLogger(SystemServiceImpl.class);

    @Override
    public void getVerifiCodeImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //获取验证码
        BufferedImage verifiCodeImage = CreateVerifiCodeImage.getVerifiCodeImage();
        String verifiCode = new String(CreateVerifiCodeImage.getVerifiCode());

        HttpSession session = request.getSession();
        session.setAttribute(SchoolConstants.VERIFICODE_KEY, verifiCode);

        ImageIO.write(verifiCodeImage, "JPEG", response.getOutputStream());
        System.out.println("验证码：" + verifiCode);
    }

    @Override
    public Result<?> login(LoginForm loginForm, HttpSession session) {
        //从 session 中取出先前生成的验证码
        String verifiCodeInSession = (String) session.getAttribute(SchoolConstants.VERIFICODE_KEY);

        //如果验证码过期
        if (verifiCodeInSession == null || verifiCodeInSession.length() == 0) {
            return Result.fail().message("验证码失效,请刷新后重试");
        }

        //如果输入错误
        if (!verifiCodeInSession.equalsIgnoreCase(loginForm.getVerifiCode())) {
            return Result.fail().message("验证码有误,请小心输入后重试");
        }

        //从 session 中删除此验证码
        session.removeAttribute(SchoolConstants.VERIFICODE_KEY);

        //密码加密
        loginForm.setPassword(MD5.encrypt(loginForm.getPassword()));

        switch (loginForm.getUserType()) {
            case SchoolConstants.ADMIN:
                return this.adminLogin(loginForm, session);
            case SchoolConstants.STUDENT:
                return this.studentLogin(loginForm, session);
            case SchoolConstants.TEACHER:
                return this.teacherLogin(loginForm, session);
        }

        return Result.fail().message("抱歉，用户名或密码错误");
    }

    @Override
    public Result getInfoByToken(String token, HttpSession session) {
        //检查 token 是否过期
        boolean expiration = JwtHelper.isExpiration(token);
        if (expiration) {//已过期
            return Result.build(null, ResultCodeEnum.TOKEN_ERROR);
        }

        //从token中解析出用户的类型
        Integer userType = JwtHelper.getUserType(token);

        //获取用户信息
        UserInfo userInfo = new UserInfo<>();
        userInfo.setUserType(userType);

        switch (userType) {
            case SchoolConstants.ADMIN:
                userInfo.setUser(session.getAttribute(SchoolConstants.ADMIN_KEY));
                session.removeAttribute(SchoolConstants.ADMIN_KEY);
                break;

            case SchoolConstants.STUDENT:
                userInfo.setUser(session.getAttribute(SchoolConstants.STUDENT_KEY));
                session.removeAttribute(SchoolConstants.STUDENT_KEY);
                break;

            case SchoolConstants.TEACHER:
                userInfo.setUser(session.getAttribute(SchoolConstants.TEACHER_KEY));
                session.removeAttribute(SchoolConstants.TEACHER_KEY);
                break;

            default:
                return Result.fail().message("登录超时，请重新登录");
        }

        return Result.ok(userInfo);
    }

    /**
     * 管理员登录
     *
     * @param loginForm 表单参数
     * @param session   session 对象
     * @return 是否登录成功
     */
    private Result<?> adminLogin(LoginForm loginForm, HttpSession session) {
        Token token = new Token();
        Admin admin = this.adminMapper.selectAdminByName(loginForm.getUsername());

        //如果用户名正确
        if (admin != null) {
            //如果密码正确
            if (admin.getPassword().equals(loginForm.getPassword())) {
                admin.setPassword("");
                token.setToken(JwtHelper.createToken(admin.getId().longValue(), SchoolConstants.ADMIN));
                session.setAttribute(SchoolConstants.ADMIN_KEY, admin);
                logger.info(loginForm.getUsername() + "登录成功");
                return Result.ok(token).message("恭喜，登录成功");
            } else {//密码错误
                return Result.fail().message("用户名或密码错误");
            }
        } else {//查询结果为空
            return Result.fail().message("用户名或密码错误");
        }
    }

    /**
     * 学生登录
     *
     * @param loginForm 表单参数
     * @param session   session 对象
     * @return 是否登录成功
     */
    private Result<?> studentLogin(LoginForm loginForm, HttpSession session) {
        Token token = new Token();
        Student student = this.studentMapper.selectStudentByName(loginForm.getUsername());

        //如果用户名正确
        if (student != null) {
            //如果密码正确
            if (student.getPassword().equals(loginForm.getPassword())) {
                student.setPassword("");
                token.setToken(JwtHelper.createToken(student.getId().longValue(), SchoolConstants.STUDENT));
                session.setAttribute(SchoolConstants.STUDENT_KEY, student);
                logger.info(loginForm.getUsername() + "登录成功");
                return Result.ok(token).message("恭喜，登录成功");
            } else {//密码错误
                return Result.fail().message("用户名或密码错误");
            }
        } else {//查询结果为空
            return Result.fail().message("用户名或密码错误");
        }
    }

    /**
     * 教师登录
     *
     * @param loginForm 表单参数
     * @param session   session 对象
     * @return 是否登录成功
     */
    private Result<?> teacherLogin(LoginForm loginForm, HttpSession session) {
        Token token = new Token();
        Teacher teacher = this.teacherMapper.selectTeacherByName(loginForm.getUsername());

        //如果用户名正确
        if (teacher != null) {
            //如果密码正确
            if (teacher.getPassword().equals(loginForm.getPassword())) {
                teacher.setPassword("");
                token.setToken(JwtHelper.createToken(teacher.getId().longValue(), SchoolConstants.TEACHER));
                session.setAttribute(SchoolConstants.TEACHER_KEY, teacher);
                logger.info(loginForm.getUsername() + "登录成功");
                return Result.ok(token).message("恭喜，登录成功");
            } else {//密码错误
                return Result.fail().message("用户名或密码错误");
            }
        } else {//查询结果为空
            return Result.fail().message("用户名或密码错误");
        }
    }

    @Override
    public Result updatePwd(String token, String oldPwd, String newPwd) {
        //验证 token 是否过期
        boolean expiration = JwtHelper.isExpiration(token);
        if (expiration) {
            // token过期
            return Result.fail().message("token失效,请重新登录后修改密码");
        }

        // 获取用户ID和用户类型
        Integer userId = JwtHelper.getUserId(token).intValue();
        Integer userType = JwtHelper.getUserType(token);

        oldPwd = MD5.encrypt(oldPwd);
        newPwd = MD5.encrypt(newPwd);

        switch (userType) {
            case SchoolConstants.ADMIN:
                //如果原密码正确
                if (this.adminMapper.selectPasswordById(userId).equals(oldPwd)) {
                    this.adminMapper.updatePasswordById(userId, newPwd);
                } else {
                    return Result.fail().message("原密码错误");
                }
                break;

            case SchoolConstants.STUDENT:
                //如果原密码正确
                if (this.studentMapper.selectPasswordById(userId).equals(oldPwd)) {
                    this.studentMapper.updatePasswordById(userId, newPwd);
                } else {
                    return Result.fail().message("原密码错误");
                }
                break;

            case SchoolConstants.TEACHER:
                //如果原密码正确
                if (this.teacherMapper.selectPasswordById(userId).equals(oldPwd)) {
                    this.teacherMapper.updatePasswordById(userId, newPwd);
                } else {
                    return Result.fail().message("原密码错误");
                }
                break;
        }

        return Result.ok();
    }

}
